#include "codec.h"

google::protobuf::Message* CreateMessage(const std::string& type_name) {
  google::protobuf::Message* message = NULL;
  const google::protobuf::Descriptor* descriptor =
      google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
          type_name);
  if (descriptor) {
    const google::protobuf::Message* prototype =
        google::protobuf::MessageFactory::generated_factory()->GetPrototype(
            descriptor);
    if (prototype) {
      message = prototype->New();
    }
  }
  return message;
}

void ProtobufCodec::OnMessage(const net::TcpConnectionPtr& conn,
                              net::Buffer* buff, Timestamp recv_time) {
  std::cout << "ProtobufCodec::OnMessage" << std::endl;
  while (buff->ReadableBytes() >= kHeaderLen + kMinMessageLen) {
    int len = buff->PeekInt32ToHost();
    if (len > kMaxMessageLen || len < kMinMessageLen) {
      LOG_ERROR << "Invalid length " << len;
      // errorCallback_();
      conn->ForceClose();
      break;
    } else if (static_cast<int>(buff->ReadableBytes()) >= kHeaderLen + len) {
      int len = buff->ReadInt32ToHost();

      int check_sum_adler = static_cast<int>(
          ::adler32(1, reinterpret_cast<const Bytef*>(buff->ReaderPtr()),
                    static_cast<uInt>(len - kHeaderLen)));

      int type_len = buff->ReadInt32ToHost();
      std::string type_name = buff->ReadString(type_len);

      std::string msgstr =
          buff->ReadString(len - sizeof(type_len) - type_len - kHeaderLen);

      int check_sum = buff->ReadInt32ToHost();
      if (check_sum != check_sum_adler) {
        LOG_ERROR << "check sum error";
        // errorCallback_();
        continue;
      }

      MessagePtr message;
      message.reset(CreateMessage(type_name));
      message->ParseFromString(msgstr);
      if (proto_msg_cb_) proto_msg_cb_(conn, message, recv_time);
    } else {
      break;
    }
  }
}